package com.pig4cloud.pigx.contract.executer.order.initializer.impl;

import com.pig4cloud.pigx.common.customize.enums.CommonDictEnum;
import com.pig4cloud.pigx.common.customize.i18n.util.MessageUtils;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.customize.utils.CommonUtil;
import com.pig4cloud.pigx.contract.bo.ContractOrderNewBO;
import com.pig4cloud.pigx.contract.constant.I18nMessages;
import com.pig4cloud.pigx.contract.enums.ContractOrderEnum;
import com.pig4cloud.pigx.contract.executer.order.initializer.OrderInitializerManager;
import com.pig4cloud.pigx.contract.mapper.ContractOrderMapper;
import com.pig4cloud.pigx.contract.mapper.ContractPositionMapper;
import com.pig4cloud.pigx.contract.mongo.entity.ContractSymbolMongo;
import com.pig4cloud.pigx.contract.utils.ContractUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * 市价单订单初始化器
 *
 * @since 2022/8/17 14:25
 */
@Component
public class MarketOrderInitializer extends AbstractOrderInitializer
		implements InitializingBean {

	protected final OrderInitializerManager orderInitializerManager;

	/**
	 * 有参构造函数
	 * <p>同时给父级对象赋值
	 *
	 * @since 2022/8/17 20:51
	 */
	public MarketOrderInitializer(ContractOrderMapper contractOrderMapper,
								  ContractPositionMapper contractPositionMapper,
								  MongoTemplate mongo,
								  AmqpTemplate rabbit,
								  CommonUtil commonUtil,
								  MysqlUtil mysqlUtil,
								  SecurityUtil securityUtil,
								  ContractUtils contractUtils,
								  OrderInitializerManager orderInitializerManager) {
		super(contractOrderMapper, contractPositionMapper, mongo, rabbit, commonUtil, mysqlUtil, securityUtil, contractUtils);
		this.orderInitializerManager = orderInitializerManager;
	}

	/**
	 * 当前对象创建后
	 *
	 * @since 2022/8/17 14:36
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		// 注册到manager
		orderInitializerManager.getInitializerList().add(this);
	}

	/**
	 * 判断是否支持
	 *
	 * @param bo 入参
	 * @return {@link boolean}
	 * @since 2022/8/17 11:20
	 */
	@Override
	public boolean support(ContractOrderNewBO bo) {
		return !Objects.equals(CommonDictEnum.YesOrNo.YES.getValue(), bo.getIsRobot())
				&& Objects.equals(ContractOrderEnum.Type.MARKET.getValue(), bo.getType());
	}

	/**
	 * 预初始化数据
	 *
	 * @param bo bo
	 * @since 2022/8/29 19:00
	 */
	@Override
	protected void preInitParam(ContractOrderNewBO bo) {
		ContractSymbolMongo symbol = contractUtils.getSymbolById(bo.getSymbolId());
		ContractUtils.checkSymbol(symbol);
		bo.setSymbol(symbol);

		// 价格
		bo.setPrice(symbol.getMarkPrice());

		super.preInitParam(bo);
	}

	/**
	 * 初始化数据
	 *
	 * @param bo bo
	 * @since 2022/8/16 22:22
	 */
	@Override
	protected void initParam(ContractOrderNewBO bo) {
		ContractSymbolMongo symbol = bo.getSymbol();

		// 手续费率
		bo.setHandlingFeeRate(symbol.getMarketFeeRate());

		super.initParam(bo);
	}

	/**
	 * 校验币对信息
	 *
	 * @param bo bo
	 * @since 2022/8/16 21:05
	 */
	@Override
	protected void validSymbol(ContractOrderNewBO bo) {
		super.validSymbol(bo);
		ContractSymbolMongo symbol = bo.getSymbol();

		// 市价单单笔最大数量
		if (symbol.getMaxMarketOrderNum().compareTo(bo.getNum()) < 0) {
			throw new RuntimeException(MessageUtils.get(I18nMessages.MAXIMUM_QUANTITY_OF_A_SINGLE_TRANSACTION_IN_MARKET_PRICE_IS, symbol.getMaxMarketOrderNum()));
		}

		// 条件市价单
		if (bo.getIsConditionPending()) {
			// 最大挂单数量
			Long pendingOrderCount = contractUtils.incrOrderPending(bo.getUserId(), 1);
			// 记录增加操作，以便下单失败后回滚
			bo.setHasAddPendingNum(true);
			if (pendingOrderCount > symbol.getMaxPendingOrderNum()) {
				throw new RuntimeException(MessageUtils.get(I18nMessages.MAXIMUM_NUMBER_OF_ORDERS_IS, symbol.getMaxPendingOrderNum()));
			}

			// 最大条件单挂单数量
			Long conditionPendingOrderCount = contractUtils.incrOrderConditionPending(bo.getUserId(), 1);
			// 记录增加操作，以便下单失败后回滚
			bo.setHasAddConditionPendingNum(true);
			if (conditionPendingOrderCount > symbol.getMaxConditionPendingOrderNum()) {
				throw new RuntimeException(MessageUtils.get(I18nMessages.MAXIMUM_NUMBER_OF_LISTED_ORDERS_IS, symbol.getMaxConditionPendingOrderNum()));
			}
		}
	}
}
